home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
tools
/
czesc_3
/
setcpu
/
expdev.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-03
|
6KB
|
200 lines
/*
SetCPU V1.60
by Dave Haynie, April 13, 1990
Released to the Public Domain
EXPANSION DEVICE MODULE
This module maintains the code used to detect and translate
a given expansion device.
*/
#include "setcpu.h"
/* ====================================================================== */
/* Stuff I need for this module. */
char *malloc();
int sscanf();
/* ====================================================================== */
/* This section manages devices with on-board ROM. The actual
implementation of this stuff is pretty well hidden in this
module. */
/* This structure manages the expansion devices that we know about. */
struct ExpDev {
struct Node node;
ULONG manuf;
ULONG board;
ULONG size;
ULONG romoffset;
ULONG romsize;
};
/* Here's the list of all the devices we know about. */
static struct List Devices =
{(struct Node *)&Devices.lh_Tail,NULL,(struct Node *)&Devices.lh_Head,0,0};
static struct ExpDev *CurrentDevice = NULL;
/* This function reads the list of expansion devices from the given file.
The file should contain data for one device per line, with the
following format:
MANUF PROD SIZE START LENGTH id-string
Except for the last field, all numbers are integers, which may be
expressed as decimal or hexidecimal. The last field is a text
string which may contain any information. It's very likely that
the line for each device will have to be supplied by the maker
of any device, since there's no way to figure out if a device's
ROM is on the same MMU page as an important I/O register which
shouldn't ever be translated. The description I use for the Amiga
2090A controller is:
0x202 0x01 0x10000 0x8000 0x4000 CBM 2090A Disk Controller
The actual fields are:
MANUF The Manufacturer's code for the PIC
PROD The Product code for the PIC
SIZE The configured size of the PIC
START The offset from the PIC base for the start of ROM
LENGTH The length of the ROM
id-string Whatever the hell you want
*/
LONG ReadExpDevs(name)
char *name;
{
FILE *file;
char buf[256],msg[256];
struct ExpDev *ed;
int len,i;
if (!(file = fopen(name,"r"))) return FALSE;
while (fgets(buf,256,file)) {
ed = (struct ExpDev *)malloc(sizeof(struct ExpDev));
if (sscanf(buf,"%lx%lx%lx%lx%lx%s",&ed->manuf,&ed->board,&ed->size,
&ed->romoffset,&ed->romsize,msg) >= 5) {
if (len = strlen(msg)) {
ed->node.ln_Name = (char *)malloc(len+1);
for (i = 0; i <= len; ++i)
ed->node.ln_Name[i] = (msg[i] == '_')?' ':msg[i];
}
if (ed->romsize = ((ed->romsize/DEVROUND)*DEVROUND))
AddHead(&Devices,(struct Node *)ed);
else
free(ed);
} else
free(ed);
}
fclose(file);
CurrentDevice = (struct ExpDev *)Devices.lh_Head;
return TRUE;
}
/* ====================================================================== */
/* This function returns the ROM information I'll need for a given
expansion device. Because of some Commodore screwups, the A2090A
appears the same device as other boards like the Commodore RAM
board. So I have the size passed as well, as a consistency
check. The returned ExpROMData structure is allocated here, and
can be freed when no longer needed. */
struct ExpROMData *GetExpROM()
{
struct ConfigDev *cd;
struct DiagArea *da;
struct ExpROMData *ed;
if (!CurrentDevice || !ExpansionBase) return NULL;
cd = FindConfigDev(NULL,CurrentDevice->manuf,CurrentDevice->board);
while (cd) {
if (((ULONG)cd->cd_BoardSize == CurrentDevice->size) &&
(cd->cd_Rom.er_Type & ERTF_DIAGVALID)) {
da = (struct DiagArea *)(((ULONG)cd->cd_BoardAddr)+((ULONG)cd->cd_Rom.er_InitDiagVec));
/* This is just a sanity check to make sure we really use the
ROM out on this card -- a nybble or byte wide ROM will be in
RAM already. */
if ((da->da_Config & DAC_BUSWIDTH) == DAC_WORDWIDE) {
ed = (struct ExpROMData *)AllocMem(SizeOf(struct ExpROMData),MEMF_CLEAR);
ed->ROMbase = ((ULONG)cd->cd_BoardAddr) + CurrentDevice->romoffset;
ed->ROMsize = CurrentDevice->romsize;
ed->imagebase = NULL;
ed->tablebase = NULL;
ed->name = (char *)AllocMem((ULONG)
strlen(CurrentDevice->node.ln_Name)+1,0L);
strcpy(ed->name,CurrentDevice->node.ln_Name);
++CurrentDevice;
return ed;
}
}
cd = FindConfigDev(cd,CurrentDevice->manuf,CurrentDevice->board);
}
CurrentDevice = (struct ExpDev *)CurrentDevice->node.ln_Succ;
return NULL;
}
/* This function removes a CardROMFile generated I/O ROM table list. */
void FreeExpROM(emem)
struct ExpROMData *emem;
{
struct ExpROMData *edel;
while (emem) {
edel = emem;
emem = emem->next;
FreeMem(edel->imagebase,edel->ROMsize);
FreeMem(edel->name,(ULONG)strlen(edel->name)+1);
FreeMem(edel,SizeOf(struct ExpROMData));
}
}
/* ====================================================================== */
/* This routine is called to configure the system devices without calling any
ROM routines that could possibly goober up on older OS releases. Other
than skipping ROMs, this should do the same thing as the ConfigChain()
function in expansion.library. */
void SafeConfigDevs()
{
struct ConfigDev *cd;
char *base = (char *)0xe80000;
if (!ExpansionBase) return;
/* Should also loop only as long as
!(ExpansionBase->eb_Flags & EBB_CLOGGED),
but I don't know what EBB_CLOGGED is yet.. */
while (cd = AllocConfigDev()) {
if (ReadExpansionRom(base,cd)) {
FreeConfigDev(cd);
break;
}
/* Got it, let's get rid of any ROM critters. */
cd->cd_Rom.er_Type &= ~ERTF_DIAGVALID;
/* Now adding the board should be safe! */
if (ConfigBoard(base,cd)) {
FreeConfigDev(cd);
break;
}
AddConfigDev(cd);
}
}